/* Test var scope and tabs */
object test1 {
  def main():Unit = { 
    //println(new Class1().initMyVar(6));
    //println(new Class1().getBool(false,true));
    //println(new Class1().getString());
    //println(new Class1().initTab());
    //println(new Class1().copyTab());
    //println(new Class1().copy2(new Class2()));
    //println(new Class1().lazyEval());
	//println(new Class2().baobab());
	//println(new Class2().stringConcat("say","my friend"));
	//println(new Class2().printClass(new Class1()));
	//println(new Class3().checkBoolEquality());
	//println(new Class3().doNothing(new Class2()).getBool(false,true));
	println(new RealMain().burp());
  }
}

class RealMain{
	def burp():Int = {
		var c1 : Class1;
		var c2: Class1;

		var array: Int[];
		var array2: Int[];
		
		if(true || 1/0 == 0){
			println("okay");
		}

		println(this.getTrue());
		c1 = new Class1();
		array = new Int[42];
		array2 = new Int[52];

		if(array == array2){
			println("Servietsky");
		}else{
			println("woops");
		}

		if(c1.getBool(true, true)){
			println("Woohoo");
		}else{
			println("woops");
		}

		if(c1.getBool(false, true)){
			println("Woohoops");
		}else{
			println("Woohoo");
		}

		if(c1.getBool(false, false)){
			println("Woohoops");
		}else{
			println("Woohoo");
		}

		if(c1.getBool(true, false)){
			println("Whoohoops");
		}else{
			println("Whoohoo");
		}
		return 42;
	}

	def getTrue(): Bool = {
		return true;
	}
}

class Class1 {
  var myVar:Int;
  var myTab:Int[];
  var myClass2:Class2;

  def initMyVar(myVar2:Int):Int = {
	var i: Int;
	var ret: Int;
    myVar = myVar2;
	myTab = new Int[myVar];
	
	i = 0;
	ret = 0;
	while(i < myTab.length)
	{
		myTab[i] = i*2;
		println(i*2);
		i = i + 1;
	}

	i = 0;

	while(i < myTab.length){
		ret  = ret + myTab[i];
		println(ret);
		i = i+1;
	}

    return ret;
  }
  
  def getBool(myBool:Bool,myBool2:Bool):Bool = { // ok
    return myBool;
  }
  
  def getString():String = { // ok
    return "hello";
  }
  
  def initTab():Int = { // ok
    myTab = new Int[3];
    myTab[0] = 25;
    
    return myTab[0];
  }
  
  def copy(c:Class2):Int = { // ok
     myVar = c.initMyVar2(7);
     
     return myVar;
  }
  
  def copy2(c:Class2):Int = {
     myClass2 = c;
     return myClass2.initMyVar2(11);
  }
  
  def copyTab():Int = {
     var aInt:Int;
     aInt = this.initTab();
     return aInt;
  }
  
  def lazyEval():Bool = {
     var aInt:Int;
     aInt = 6;
     
     if (false && (aInt/0 < 2)) {
       aInt = 88;
     }
     
     return aInt==88;
  }
  
  def getThis(): Class1 = {
     myVar=45;
     myTab = new Int[1];
     myTab[0] = 77;
  
     return this;
  }
}

class Class2 extends Class1 {
   var myVar2:Int;
   var tab: Int[];
   var name : String;
   
   def initMyVar2(myVar:Int):Int = {
      myVar2 = myVar;
      
      return myVar2;
   }
   
   def setTab(tab:Int[]):Int = {
      tab = tab;
      return tab[0];
   }

   def baobab(): String = {
	   var i : Int;
	   var b : Int;

	   b = 1;

	   i = 10;


	   while(!(i == (b -1 ))){
		   println("arfarf");
		   i = i - 1;
	   }
	   return "";
   }
   
   def getString():String = {
      return "times";
   }
   
   def stringConcat(str1:String,str2:String):String = {
      return str1 + " hello " + str2 + " " + 2 + " " + this.getString();
   }
   
   def print() : String = {
      name = "my name";
      return name + "is bond";
   }
   
   def printClass(c1:Class1):String = {
      var class1:Class1;
      var str:String;
      
      class1 = c1.getThis();
      str = "" + class1.initMyVar(5);
      
      return str;
   }
   
   def getBool(myBool:Bool,myBool2:Bool):Bool = { // ok
    return myBool2;
  }
}

class Class3 extends Class2{
   def doNothing(c2 : Class2):Class1 = {
      return c2;
   }
   
   def checkBoolEquality():Bool = {
      return true == false;
   }

   def getBool(myBool: Bool, myBool2:Bool):Bool = {
      return myBool && myBool2;
   }
}
